/*
 * @Description:
 * @Author: qingyang
 * @Date: 2021-06-01 13:42:35
 * @LastEditors: qingyang
 * @LastEditTime: 2023-05-22 14:28:46
 */
import { ActionTree } from 'vuex';
import { UserState } from './state';
import { RootState } from '@/store';
import { UserActionTypes } from './action-types';
import { UserMutationTypes } from './mutation-types';
import { getManagerInfo, getSupplerInfo, getMenu } from '@/apis/user/user';
import auth from '@/utils/auth';
import { authPost } from '@/utils/user.axios';
import type { OAuthParams } from '@/utils/user.axios';
import config from '@/config';
import type { IUserParams, IUserData } from '@/apis/user/model/userModel';
import { generateRoutes } from '@/router/permission';
import { getMenuTree } from '@/utils/user.utils';
import { useAboutLogin } from '@/hooks/useAboutLogin';
import type { UrlTokenParamsType, LoginType, LoginSource } from '@/hooks/LoginFactory.class';

export interface Actions {
  [UserActionTypes.ACTION_LOGIN](
    { commit }: any,
    {
      userInfo,
      loginType
    }: {
      userInfo: (IUserParams & IUserData) | UrlTokenParamsType;
      loginType: LoginType;
    }
  ): void;
  [UserActionTypes.ACTION_LOGIN_OUT]({
    state,
    dispatch
  }: {
    state: UserState;
    dispatch: Actions;
  }): void;
  [UserActionTypes.ACTION_GET_ACCESS_TOKEN]({ commit }: any): Promise<any>;
  [UserActionTypes.ACTION_CHECK_LOGIN_STATUS]({ commit }: any): void;
  [UserActionTypes.ACTION_CHANGE_ROLES]({ commit }: any): Promise<any>;
  [UserActionTypes.ACTION_SET_ROUTES]({ commit }: any, roles: string[]): Promise<any>;
  [UserActionTypes.ACTION_CLEAR_LOGIN_INFO]({ commit }: any): void;
}

export const actions: ActionTree<UserState, RootState> & Actions = {
  async [UserActionTypes.ACTION_LOGIN](
    { commit }: any,
    {
      userInfo,
      loginType,
      loginSource = 'ADMIN'
    }: {
      userInfo: (IUserParams & IUserData) | UrlTokenParamsType;
      loginType: LoginType;
      loginSource: LoginSource;
    }
  ) {
    const { handleLoginReq } = useAboutLogin();
    try {
      const data = await handleLoginReq(userInfo, loginType, loginSource);
      if (data.access_token) {
        localStorage.setItem('token', data.access_token);
      }
      localStorage.setItem('name', data.username);
      // 保存登录信息至localStorage
      auth.saveLoginInfo(data);
      commit(UserMutationTypes.SHOW_LOGIN, false);
      commit(UserMutationTypes.SET_LOGIN_STATUS, true);
      return Promise.resolve(data);
    } catch (err) {
      commit(UserMutationTypes.SET_LOGIN_STATUS, false);
      return Promise.reject(err);
    }
  },
  // 登出
  [UserActionTypes.ACTION_LOGIN_OUT]({ state, dispatch }: any) {
    console.log('ACTION_LOGIN_OUT', state.userType);
    dispatch(UserActionTypes.ACTION_CLEAR_LOGIN_INFO);
    // 登出跳转
    const { handleLogoutJump } = useAboutLogin();
    handleLogoutJump();
  },
  // 获取token
  async [UserActionTypes.ACTION_GET_ACCESS_TOKEN]() {
    return new Promise((resolve, reject) => {
      const expiresIn = localStorage.getItem('expires_in');
      const nowTime = new Date().getTime();
      if (!expiresIn || nowTime >= parseInt(expiresIn)) {
        console.log('token过期，需要重新获取');
        if (localStorage.getItem('token') === 'refreshing') {
          console.log('token正在刷新中');
          let time = 0;
          const timer = setInterval(() => {
            time++;
            const token = localStorage.getItem('token');
            console.log('循环定时器：判断token的值：', token);
            // token刷新失败（refresh_token也过期了）
            if (!token) {
              clearInterval(timer);
              return reject(new Error('登录信息已过期，请重新登录'));
            }
            // token刷新完成
            if (token && token !== 'refreshing') {
              clearInterval(timer);
              return resolve(token);
            }
            // 等待超时
            if (time * 500 > config.TIMEOUT) {
              clearInterval(timer);
              return reject(new Error('获取token超时'));
            }
          }, 500);
        } else {
          console.log('token未刷新，需要刷新');
          localStorage.setItem('token', 'refreshing');
          try {
            const refreshToken = window.localStorage.getItem('refresh_token')
              ? window.localStorage.getItem('refresh_token')
              : '';
            if (!refreshToken) {
              return reject(new Error('登录状态已过期，请重新登录'));
            }
            const params: OAuthParams = {
              grant_type: 'refresh_token',
              refresh_token: refreshToken,
              scope: 'server'
            };
            authPost(params)
              .then((res: any) => {
                console.log(`新token: ${res.data.access_token}`, res.data);
                auth.saveLoginInfo(res.data);
                return resolve(res.data.access_token);
              })
              .catch((err: any) => {
                console.log('token刷新失败', err);
                return reject(err);
              });
          } catch (err: any) {
            console.log('refresh token失败', err, err.message);
            reject(err);
          }
        }
      } else {
        console.log(`token没有过期，token：${localStorage.getItem('token')}`);
        return resolve(localStorage.getItem('token'));
      }
    });
  },
  // 检查登录状态
  [UserActionTypes.ACTION_CHECK_LOGIN_STATUS]({ commit, dispatch }: any) {
    const token = localStorage.getItem('token');
    const expiresIn = localStorage.getItem('expires_in');
    const refreshToken = localStorage.getItem('refresh_token');
    console.log('检查登录状态', token, expiresIn, refreshToken);
    if (token && expiresIn && refreshToken && token !== 'refreshing') {
      commit('SET_LOGIN_STATUS', true);
    } else {
      commit('SET_LOGIN_STATUS', false);
      // 清空登录信息
      dispatch(UserActionTypes.ACTION_CLEAR_LOGIN_INFO);
    }
  },
  async [UserActionTypes.ACTION_CHANGE_ROLES]({ state, commit }: any) {
    try {
      console.log('state.userType', state.userType);
      let res;
      if (state.userType === 'SUPPLIER' || state.userType === 'JWT') {
        console.log('state.userType 供应商数据获取');
        res = await getSupplerInfo();
      } else {
        res = await getManagerInfo();
      }
      const roleCodes = res.roleCodes || [];
      const { user, permissions } = res;
      commit(UserMutationTypes.SET_USER_INFO, { ...user, roleCodes });
      // 设置按钮权限store
      commit(UserMutationTypes.SET_PERMISSIONS, permissions);
      // 角色codes
      commit(UserMutationTypes.SET_ROLES, roleCodes);
      if (state.userType !== 'SUPPLIER' && state.userType !== 'JWT') {
        const menuInfo = await getMenu();
        getMenuTree(menuInfo);
        if (roleCodes.includes('eps_user')) {
          commit(UserMutationTypes.SET_USER_TYPE, 'EPS');
        }
      }
      return Promise.resolve(roleCodes);
    } catch (err) {
      return Promise.reject(err);
    }
  },
  [UserActionTypes.ACTION_SET_ROUTES]({ commit }: any, roles: string[]) {
    return new Promise(resolve => {
      const accessRoutes = generateRoutes(roles);
      commit(UserMutationTypes.SET_ROUTES, accessRoutes);
      resolve(accessRoutes);
    });
  },
  // 清空登录信息
  [UserActionTypes.ACTION_CLEAR_LOGIN_INFO]({ commit }: any) {
    localStorage.removeItem('expires_in');
    localStorage.removeItem('refresh_token');
    localStorage.removeItem('token');
    localStorage.removeItem('name');
    localStorage.removeItem('id');
    localStorage.removeItem('user-type');
    localStorage.removeItem('enterpriseNo');
    commit(UserMutationTypes.SET_ROLES, []);
    commit(UserMutationTypes.SET_LOGIN_STATUS, false);
    commit(UserMutationTypes.SET_PERMISSIONS, []);
    commit(UserMutationTypes.SET_MENU_LIST, []);
    commit(UserMutationTypes.SET_SIDEMENUS, []);
    commit(UserMutationTypes.SET_ROUTES, []);
    commit(UserMutationTypes.SET_USER_INFO, {});
  }
};
